package com.antd.admin.server.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.antd.admin.api.dto.RoleDTO;
import com.antd.admin.api.entity.SysRole;
import com.antd.admin.api.entity.SysRoleDept;
import com.antd.admin.api.entity.SysRoleMenu;
import com.antd.admin.api.entity.SysUserRole;
import com.antd.admin.server.mapper.SysRoleMapper;
import com.antd.admin.server.service.ISysRoleDeptService;
import com.antd.admin.server.service.ISysRoleMenuService;
import com.antd.admin.server.service.ISysRoleService;
import com.antd.admin.server.service.ISysUserRoleService;
import com.antd.admin.server.strategy.data.DataScopeContext;
import com.antd.common.core.exception.BaseException;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统角色表 服务实现类
 * </p>
 *
 * @author 子丶沫
 * @since 2020-11-18
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Autowired
    private DataScopeContext dataScopeContext;
    @Autowired
    private ISysRoleDeptService roleDeptService;
    @Autowired
    private ISysUserRoleService userRoleService;
    @Autowired
    private ISysRoleMenuService roleMenuService;
    @Override
    public List<SysRole> findRoleByUserId(String userId) {
        return baseMapper.findRoleByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRole(List<String> roleIdList) {
        List<SysUserRole> list = userRoleService.list(Wrappers.<SysUserRole>query().lambda().in(SysUserRole::getRoleId, roleIdList));
        if(CollectionUtil.isNotEmpty(list)){
            throw new BaseException("角色下有用户，无法删除");
        }
        roleIdList.forEach(roleId->{
            baseMapper.delete(Wrappers.<SysRole>update().lambda().eq(SysRole::getRoleId, roleId));
            roleDeptService.remove(Wrappers.<SysRoleDept>update().lambda().eq(SysRoleDept::getRoleId, roleId));
            roleMenuService.remove(Wrappers.<SysRoleMenu>update().lambda().eq(SysRoleMenu::getRoleId,roleId));
        });
        return true;
    }

    /**
     * 保存角色
     * @param roleDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertRole(RoleDTO roleDTO) {
        SysRole role=new SysRole();
        BeanUtils.copyProperties(roleDTO,role);
        List<String> ids = dataScopeContext.getDeptIdsForDataScope(roleDTO, roleDTO.getDsType());
        StringJoiner dataScope = new StringJoiner(",");
        ids.forEach(dataScope::add);
        role.setDsScope(dataScope.toString());
        int insert = baseMapper.insert(role);
        return saveRoleDept(role, ids, insert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRole(RoleDTO roleDTO) {
        SysRole sysRole=SysRole.builder().build();
        BeanUtils.copyProperties(roleDTO,sysRole);
        List<String> ids = dataScopeContext.getDeptIdsForDataScope(roleDTO, roleDTO.getDsType());
        StringJoiner dsScope=new StringJoiner(",");
        ids.forEach(dsScope::add);
        sysRole.setDsScope(dsScope.toString());
        int update = baseMapper.updateById(sysRole);
        roleDeptService.remove(Wrappers.<SysRoleDept>query().lambda().eq(SysRoleDept::getRoleId,roleDTO.getRoleId()));
        return saveRoleDept(sysRole, ids, update);
    }

    @Override
    public IPage<SysRole> queryRoleList(Page<SysRole> page, SysRole role) {
        IPage<SysRole> list = baseMapper.selectPage(page,Wrappers.<SysRole>query().lambda().like(StrUtil.isNotBlank(role.getRoleName()), SysRole::getRoleName, role.getRoleName()));
        List<SysRole> roleList = list.getRecords().stream()
                .peek(sysRole -> sysRole.setRoleDepts(roleDeptService.getRoleDeptIds(sysRole.getRoleId())))
                .peek(sysRole->sysRole.setRoleMenuIds(roleMenuService.queryRolePermission(sysRole.getRoleId())))
                .collect(Collectors.toList());
        list.setRecords(roleList);
        return list;
    }

    private boolean saveRoleDept(SysRole role, List<String> ids, int update) {
        if(CollectionUtil.isNotEmpty(ids)){
            List<SysRoleDept> roleDeptList = ids.stream().map(deptId -> {
                SysRoleDept roleDept = new SysRoleDept();
                roleDept.setDeptId(deptId);
                roleDept.setRoleId(role.getRoleId());
                return roleDept;
            }).collect(Collectors.toList());
            roleDeptService.saveBatch(roleDeptList);
        }
        return update>0;
    }
}
